package gb

import (
	"encoding/xml"
	"fmt"
	"net/http"
	"strings"

	"gitee.com/tonyjia/gb28181/pkg/gbsip"
	model2 "gitee.com/tonyjia/gb28181/pkg/model"
	"gitee.com/tonyjia/gb28181/pkg/model/constant"
	"gitee.com/tonyjia/gb28181/pkg/parser"
	"github.com/ghettovoice/gosip"
	"github.com/ghettovoice/gosip/sip"
	log "github.com/sirupsen/logrus"
)

/**
 * @Description
 * @Author lulili
 * @Date 2024/10/17 16:22
 */

var (
	messageHandler = map[string]gosip.RequestHandler{
		"Notify:Keepalive": keepaliveNotifyHandler,
		"Notify:Catalog":   catalogNotifyHandler,
		// 查询设备信息响应
		"Response:DeviceInfo": deviceInfoHandler,
		"Response:Catalog":    catalogHandler,
		//查询设备目录信息
		"Query:Catalog":    catalogQueryHandler,
		"Query:DeviceInfo": deviceQueryHandler,
	}
)

func MessageHandler(req sip.Request, tx sip.ServerTransaction) {
	log.Debug("处理MESSAGE消息...")
	if l, ok := req.ContentLength(); !ok || l.Equals(0) {
		log.Debug("该MESSAGE消息的消息体长度为0，返回OK")
		_ = tx.Respond(sip.NewResponseFromRequest("", req, http.StatusOK, http.StatusText(http.StatusOK), ""))
	}
	body := req.Body()
	cmdType, err := parser.GetCmdTypeFromXML(body)
	log.Debug("解析出的命令：", cmdType)
	if err != nil {
		return
	}
	handler, ok := messageHandler[cmdType]
	if !ok {
		log.Errorf("不支持的Message【%s】方法实现", cmdType)
		return
	}
	handler(req, tx)
}

func deviceInfoHandler(req sip.Request, tx sip.ServerTransaction) {
	// 回复ACK
	defer func() {
		_ = responseAck(tx, req)
	}()

	d := &model2.DeviceInfo{}
	decoder := xml.NewDecoder(strings.NewReader(req.Body()))
	decoder.CharsetReader = gb2312CharsetReader
	if err := decoder.Decode(&d); err != nil {
		log.Error("解析响应包出错", err)
		return
	}

	if d.Result != constant.ResultOK {
		log.Errorf("查询设备信息请求结果为%s，请检查", d.Result)
		return
	}
	//将设备信息传递给上级平台
	device := model2.Device{
		Name:         d.DeviceName,
		Manufacturer: d.Manufacturer,
		Model:        d.Model,
		Firmware:     d.Firmware,
		DeviceID:     d.DeviceID,
	}
	err := gbsip.SyncDeviceInfo(device)
	if err != nil {
		log.Errorf("传递设备%v信息失败: %v", device, err)
		return
	}

}

func catalogQueryHandler(req sip.Request, tx sip.ServerTransaction) {
	//1. send 200 ok response
	responseAck(tx, req)
	//2 send catalog response
	d := &model2.DeviceInfo{}
	log.Infof("接收到请求为%v", req)
	decoder := xml.NewDecoder(strings.NewReader(req.Body()))
	decoder.CharsetReader = gb2312CharsetReader

	if err := decoder.Decode(&d); err != nil {
		log.Error("解析响应包出错", err)
		return
	}
	//回调接口查询设备通道
	device := model2.Device{DeviceID: d.DeviceID}
	channels, err := gbsip.GetCatalogInfo(device)
	if err != nil {
		return
	}
	//将channels转化为xml
	xmlStr, err := parser.CreateCatalogResponseXml(parser.CatalogCmdType, d.DeviceID, d.SN, channels)
	if err != nil {
		log.Errorf("构造内容失败:%v", err)
	}
	//获取via地址，如果有多个只取第一个
	via, _ := req.Via()
	from, _ := req.From()
	port := fmt.Sprintf("%d", *via[0].Port)
	err = gbsip.QueryMessageResponse(from.Address.User().String(), via[0].Host, port, xmlStr)
	if err != nil {
		log.Error("通道信息返回失败", err)
		return
	}
	return
}

func deviceQueryHandler(req sip.Request, tx sip.ServerTransaction) {
	d := &model2.DeviceInfo{}
	log.Infof("接收到查询设备请求为%v", req)
	//先回复一个200ok确认消息
	responseAck(tx, req)
	decoder := xml.NewDecoder(strings.NewReader(req.Body()))
	decoder.CharsetReader = gb2312CharsetReader
	if err := decoder.Decode(&d); err != nil {
		log.Error("解析响应包出错", err)
		return
	}
	//回调接口查询设备
	device := model2.Device{DeviceID: d.DeviceID}
	device, err := gbsip.QueryDeviceInfo(device)
	if err != nil {
		log.Error("查询设备信息失败", err)
		return
	}
	//将channels转化为xml
	xmlStr, err := parser.CreateDeviceResponseXml(parser.DeviceInfoCmdType, d.SN, device)
	if err != nil {
		log.Errorf("构造内容失败:%v", err)
	}
	via, _ := req.Via()
	from, _ := req.From()
	port := fmt.Sprintf("%d", *via[0].Port)
	err = gbsip.QueryMessageResponse(from.Address.User().String(), via[0].Host, port, xmlStr)
	if err != nil {
		log.Error("设备信息返回", err)
		return
	}
}
func catalogHandler(req sip.Request, tx sip.ServerTransaction) {
	defer func() {
		_ = responseAck(tx, req)
	}()

	catalog := model2.DeviceCatalogResponse{}
	decoder := xml.NewDecoder(strings.NewReader(req.Body()))
	decoder.CharsetReader = gb2312CharsetReader
	if err := decoder.Decode(&catalog); err != nil {
		log.Error("解析响应包出错", err)
		return
	}

	var channels []model2.Channel
	for _, item := range catalog.DeviceList.Items {
		c := item.ConvertToChannel()
		channels = append(channels, c)
	}
	// 向平台同步通道信息
	err := gbsip.SyncCatalog(channels)
	if err != nil {
		log.Error("同步通道信息失败", err)
		return
	}
	return
}
